// <editor-fold defaultstate="collapsed" desc="GNU GPLv3 header">
/* 
 * File:   main.c
 *
 * Copyright (C) 2013 Robert Antoni Buj Gelonch <rbuj@uoc.edu>
 * Copyright (C) 2013 David Megias Jimenez <dmegias@uoc.edu>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="defines">
#ifndef FCY
#define FCY 40000000UL // 40 MIPS
#endif
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="includes">
#include <stdio.h>
#include <stdlib.h>
#include <p33FJ256GP710A.h>
#include <libpic30.h>
#include "../include/LCD_TM162JCAWG1.h"
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="osc config">
/*
 * Fosc = Fin x (M / (N1 x N2))
 * Fcy = MIPS = Fosc / 2
 *
 * XTAL Explorer 16 = 8 MHz
 *
 * Fosc = 8 MHz x (40 / (2x2) = 80 MHz
 * Fcy = MIPS = 80 MHz / 2 = 39613750 IPS = 40 MIPS
 *
 */
/* Primary Oscillator (POSC) on the OSC1 and OSC2 pins 8 MHz */
_FOSCSEL(FNOSC_PRIPLL);

/* Enable clock switcing and configure */
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);

/* Watchdog Timer: OFF */
_FWDT(FWDTEN_OFF);
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="const declaration">
const unsigned char mytext_A[] = "Hello World !!";
const unsigned char mytext_B[] = ">>>> I'm a dsPIC";
// </editor-fold>

/* main program
 * byval argc
 * byref argv
 */
int main(int argc, char** argv) {
    unsigned int cursor;
    // Configure PLL prescaller, PLL postscaller. PLL divisor
    PLLFBD = 38; // M = 40
    CLKDIVbits.PLLPOST = 0; // N2=2
    CLKDIVbits.PLLPRE = 0; // N1=2

    // Initiate Clock Switch to Primary Oscillator with PLL (NOSC = 0b011)
    __builtin_write_OSCCONH(0x03);
    __builtin_write_OSCCONL(0x01);

    // Wait for Clock switch to occur
    while (OSCCONbits.COSC != 0b011);

    // Wait for PLL to lock
    while (OSCCONbits.LOCK != 1) {
    };

    /* set LEDs (D3-D10/RA0-RA7) drive state low */
    LATA = 0xFF00;
    /* set LED pins (D3-D10/RA0-RA7) as outputs */
    TRISA = 0xFF00;

    lcd_init();

    lcd_home_clr();
    lcd_puts((unsigned char*) &mytext_A[0], sizeof (mytext_A) - 1);
    lcd_line_2();
    lcd_puts((unsigned char*) &mytext_B[0], sizeof (mytext_B) - 1);
    while (1) {
        __delay32(FCY); // delay 1 second
        for (cursor = 0; cursor < 16; cursor++) {
            lcd_display_shift_right();
            __delay32(FCY); // delay 1 second
        }
        lcd_home_it();
    }
    return (EXIT_SUCCESS);
}
